﻿#pragma once
#ifndef LOWLEVEL_H
#define LOWLEVEL_H

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <climits>
#include <exception>
#include <new>
#include <type_traits>
#if defined(_MSC_VER)
#include <intrin.h>
#endif
#if defined(__clang__) || defined(__llvm__)
#include <cpuid.h>
#endif


///@addtogroup Diverse
///@{
///@addtogroup LowLevel
///@brief Makros und Hilfsstrukturen, f�r Compiler/Architektur �bergreifende Kompatibilit�t.
///@{

#ifndef DOXYGEN_SHOULD_SKIP_THIS

#if defined(_MSC_VER) || defined(MAVC)
#define PACK __declspec(align(1))
#define ALIGN(VALUE) __declspec(align(VALUE))
#define FASTCALL __fastcall
#define CCALL __cdecl
#define STDCALL __stdcall
#define DLLIMPORT __declspec(dllimport)
#define DLLEXPORT __declspec(dllexport)
#define PREVENTINLINE __declspec(noinline)
#define RESTRICT __restrict

#if (_MSC_VER >= 1200) && !defined(FORCEINLINE)
#define FORCEINLINE __forceinline
#elif !defined(FORCEINLINE)
#define FORCEINLINE __inline
#endif

#define THREADLOCAL __declspec(thread)
#define FUNCTION __FUNCTION__
#define BREAKPOINT __debugbreak()
#define ASSUME(TEST) __assume(TEST)

#elif defined(__GNUC__)
#define PACK __attribute__((__packed__))
#define ALIGN(VALUE) __attribute__((aligned(VALUE)))
#define FASTCALL __attribute__((fastcall))
#define CCALL __attribute__((cdecl))
#define STDCALL __attribute__((stdcall))
#define DLLIMPORT __attribute__((dllimport))
#define DLLEXPORT __attribute__((dllexport))
#define PREVENTINLINE __attribute__((noinline))
#define RESTRICT __restrict__
#if !defined(FORCEINLINE)
#define FORCEINLINE __attribute__((always_inline)) inline
#endif
#define THREADLOCAL __thread
#define FUNCTION __func__
#define BREAKPOINT __builtin_trap()
#define ASSUME(TEST) do { if (!(TEST)) __builtin_unreachable(); } while (0)
#elif defined(__llvm__) || defined(__clang__)
#define PACK __attribute__((__packed__))
#define ALIGN(VALUE) __attribute__((aligned(VALUE)))
#define FASTCALL __attribute__((fastcall))
#define CCALL __attribute__((cdecl))
#define STDCALL __attribute__((stdcall))
#define DLLIMPORT __attribute__((dllimport))
#define DLLEXPORT __attribute__((dllexport))
#define PREVENTINLINE __attribute__((noinline))
#define RESTRICT __restrict__
#if !defined(FORCEINLINE)
#define FORCEINLINE __attribute__((always_inline)) inline
#endif
#define THREADLOCAL __thread
#define FUNCTION __func__
#define BREAKPOINT __builtin_trap()
#define ASSUME(TEST) do { if (!(TEST)) __builtin_unreachable(); } while (0)
#else
#define PACK <!?ERROR?!>
#define ALIGN(VALUE) <!?ERROR?!>
#define FASTCALL <!?ERROR?!>
#define CCALL <!?ERROR?!>
#define STDCALL <!?ERROR?!>
#define DLLIMPORT <!?ERROR?!>
#define DLLEXPORT <!?ERROR?!>
#if !defined(FORCEINLINE)
#define FORCEINLINE inline
#endif
#define THREADLOCAL thread_local
#define ASSUME(TEST) do {} while (false)
#error Not supported compiler
#endif

#if defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__amd64__) || defined(__X86_64__) || defined(__amd64) || defined(__X86_64) || defined(_M_X64) || defined(_M_AMD64)
#define PROCESSOR_X64 (1)
#else
#define PROCESSOR_X64 (0)
#endif
#if (!PROCESSOR_X64) && (defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || defined(_X86_) || defined(__I86__))
#define PROCESSOR_X86 (1)
#else
#define PROCESSOR_X86 (0)
#endif
#if PROCESSOR_X64 || PROCESSOR_X86
#define PROCESSOR_X86_X64 (1)
#else
#define PROCESSOR_X86_X64 (0)
#endif

#if defined(_MSC_VER) || defined(MAVC) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(WIN32) || defined(_WIN32) || defined(__WIN32)
#define WINDOWS 1
#else
#define WINDOWS 0
#endif
#if defined(__linux) || defined(__linux__)
#define LINUX 1
#else
#define LINUX 0
#endif
#if defined(unix) || defined(__unix) || defined(__unix__)
#define UNIX 1
#else
#define UNIX 0
#endif
#if defined(__APPLE__) || defined(__MACH__)
#define MACOS 1
#else
#define MACOS 0
#endif
#if defined(__FreeBSD) || defined(__FreeBSD__)
#define FREEBSD 1
#else
#define FREEBSD 0
#endif
#if MACOS || FREEBSD
#define BSD 1
#else
#define BSD 0
#endif
#if defined(__posix) || defined(posix) || UNIX || LINUX || BSD
#define POSIX 1
#else
#define POSIX 0
#endif




#else
///@brief Ein Variablen-/Strukturattribut das angibt, dass die Variable direkt ohne Alignment gepackt werden soll.
#define PACK 
///@brief Ein Funktionsattribut das angibt, dass die Funktion mit der Fastcall-Konvention aufgerufen werden soll.
#define FASTCALL
///@brief Ein Funktionsattribut das angibt, dass die Funktion mit der Ccall-Konvention aufgerufen werden soll.
#define CCALL
///@brief Ein Funktionsattribut das angibt, dass die Funktion mit der Stdcall-Konvention aufgerufen werden soll.
#define STDCALL
///@brief Ein Funktionsattribut das angibt, dass die Funktion DLL imporiert werden soll.
#define DLLIMPORT
///@brief Ein Funktionsattribut das angibt, dass die Funktion DLL exportiert werden soll.
#define DLLEXPORT
///@brief Ein Funktionsattribut das angibt, dass dem Compiler angibt, dass diese Funktion auf jeden Fall geinlined werden muss.
#define FORCEINLINE
///@brief Definition f�r verbesserten C++11 Support.
#define thread_local
///@brief Wenn dieser Pr�prozessorwert nicht mit 0 definiert ist, dann wird Code f�r einen x64 Prozessor erzeugt
#define PROCESSOR_X64
///@brief Wenn dieser Pr�prozessorwert nicht mit 0 definiert ist, dann wird Code f�r einen x86 Prozessor erzeugt
#define PROCESSOR_X86
///@brief Wenn dieser Pr�prozessorwert nicht mit 0 definiert ist, dann wird Code f�r die Windowsplatform erzeugt.
#define WINDOWS

///@cond NO_DOCU
#error That is documentation. Your compiler should not compile this.
///@endcond
#endif

#if defined(PROCESSOR_X86_X64) && !defined(LITTLEENDIAN_C)
#define LITTLEENDIAN_C
#endif

#if defined(LITTLEENDIAN_C) && defined(BIGENDIAN_C)
#error LITTLEENDIAN_C and BIGENDIAN_C defined!
#elif defined(LITTLEENDIAN_C)
#define LITTLEENDIAN 1
#elif defined(BIGENDIAN_C)
#define BIGENDIAN 1
#else
#if defined(__LITTLE_ENDIAN__) && defined(__BIG_ENDIAN__)
#error __LITTLE_ENDIAN__ and __BIG_ENDIAN__ defined!
#elif defined(__LITTLE_ENDIAN__)
#define LITTLEENDIAN 1
#elif defined(__BIG_ENDIAN__)
#define BIGENDIAN 1
#else
#error Endianness unknown: Define LITTLEENDIAN_C or BIGENDIAN_C.
#define LITTLEENDIAN 1
#endif
#endif




/*#ifdef _MSC_VER
#define EXCTRY \
__try \
{
#define EXCFINALLY(...) \
} \
__finally \
{ \
__VA_ARGS__ \
}
#else*/
#define EXCTRY \
	try \
	{
#define EXCFINALLY(...) \
	} \
	catch (...) \
	{  \
	__VA_ARGS__ \
	throw; \
	} \
	{ \
	__VA_ARGS__ \
	}
//#endif

#define ALLOCA_MAXSIZE(TYPE) (16384 / sizeof(TYPE))
#ifndef DOXYGEN_SHOULD_SKIP_THIS
#if WINDOWS || LINUX || BSD
#if WINDOWS
#define ALLOCA_FUNCNAME _alloca
#elif LINUX
#include <alloca.h>
#define ALLOCA_FUNCNAME alloca
#else
#define ALLOCA_FUNCNAME alloca
#endif
#define ALLOCA(TYPE,NAME,SIZE) \
	TYPE* NAME = reinterpret_cast<TYPE*>(ALLOCA_FUNCNAME(sizeof(TYPE)* SIZE)); \
do {} while (0)
#define ALLOCA_CONDITIONAL(TYPE,NAME,SIZE,CONDITION) \
	TYPE* const NAME = (CONDITION) ? reinterpret_cast<TYPE*>(ALLOCA_FUNCNAME(sizeof(TYPE)* SIZE)) : nullptr; \
do {} while (0)
#else
#define ALLOCA(TYPE,NAME,SIZE) \
	char NAME ## RawBuffer[sizeof(TYPE)* ALLOCA_MAXSIZE(TYPE)]; \
	TYPE* const NAME = NAME ## RawBuffer; \
do {} while (0)
#define ALLOCA_CONDITIONAL(TYPE,NAME,SIZE,CONDITION) ALLOCA(TYPE,NAME,SIZE)
#warning Inefficient ALLOCA and ALLOCA_CONDITIONAL on this operating system
#endif
#else
#define ALLOCA(TYPE,NAME,SIZE) <Implementierungsabh�nig>
#define ALLOCA_CONDITIONAL(TYPE,NAME,SIZE,CONDITION) <Implementierungsabh�nig>
///@cond NO_DOCU
#error That is documentation. Your compiler should not compile this.
///@endcond
#endif

///@brief Makro, das uninitialisierten Speicher bei kleinen Mengen auf dem Stack reserviert und bei Gr��eren auf dem langsameren Heap.
///@details
///@warning Es sollte nicht vergessen werden, nach der Benutzung auch wieder "FASTDELETEMEMORY" aufzurufen! (Ausnahmesicherheit)
///@warning Der Speicher ist uninitialisiert. Ggf. Placement-New aufrufen!
///@sa FASTDELETEMEMORY
#define FASTNEWMEMORY(TYPE,NAME,COUNT) \
	const std::size_t NAME ## FixedBufferObjectCount = ALLOCA_MAXSIZE(TYPE); \
	const std::size_t NAME ## FixedBufferSize = NAME ## FixedBufferObjectCount * sizeof(TYPE); \
	const std::size_t NAME ## Count = (COUNT); \
	ALLOCA_CONDITIONAL(char, NAME ## FixedBuffer, NAME ## FixedBufferSize, NAME ## Count <= NAME ## FixedBufferObjectCount); \
	TYPE* const NAME = reinterpret_cast<TYPE*>(\
	NAME ## Count > NAME ## FixedBufferObjectCount ? \
	std::malloc(NAME ## Count * sizeof(TYPE)) : \
	NAME ## FixedBuffer); \
do {} while (0)

///@brief Makro, das den Speicher freigibt, der mit "FASTNEWMEMORY" reserviert wurde. 
///@details
///@sa FASTNEWMEMORY
#define FASTDELETEMEMORY(NAME) \
if (NAME ## Count > NAME ## FixedBufferObjectCount) \
	std::free(NAME); \
do {} while (0)

//template<typename T, std::size_t MaxStackSize = ALLOCA_MAXSIZE(T)>
//class StackOptimizedAlloc{};

///@brief Makro, f�r die automatische sichere Speicherreservierung und Freigabe auch bei Ausnahmen.
///@details
///@sa StackOptimizedAlloc
/*
#define FASTNEWMEMORY_SAFE_BEGIN(TYPE,NAME,COUNT) \
	{
\
	FASTNEWMEMORY(TYPE, NAME, COUNT); \
	EXCTRY \
{
#define FASTNEWMEMORY_SAFE_END(NAME) \
} \
	EXCFINALLY(FASTDELETEMEMORY(NAME);); \
}*/

	///@}
	///@}
#define COMBINE(...) __VA_ARGS__

#if defined(_MSC_VER) && _MSC_VER < 1800
#define OPERATOR_EXPLICIT 
#define CONSTEXPR const
#else
#define OPERATOR_EXPLICIT explicit
#define CONSTEXPR constexpr
#endif
#if defined(_MSC_VER) && _MSC_VER < 1700
#define FINAL
#else
#define FINAL final
#endif


	//Ror & Rol
	namespace Private
	{
		static FORCEINLINE std::uint8_t ROL8function(std::uint8_t Value, unsigned int Shift)
		{
			return (Value << Shift) | (Value >> (8 - Shift));
		}
		static FORCEINLINE std::uint8_t ROR8function(std::uint8_t Value, unsigned int Shift)
		{
			return (Value >> Shift) | (Value << (8 - Shift));
		}
		static FORCEINLINE std::uint16_t ROL16function(std::uint16_t Value, unsigned int Shift)
		{
			return (Value << Shift) | (Value >> (16 - Shift));
		}
		static FORCEINLINE std::uint16_t ROR16function(std::uint16_t Value, unsigned int Shift)
		{
			return (Value >> Shift) | (Value << (16 - Shift));
		}
		static FORCEINLINE std::uint32_t ROL32function(std::uint32_t Value, unsigned int Shift)
		{
			return (Value << Shift) | (Value >> (32 - Shift));
		}
		static FORCEINLINE std::uint32_t ROR32function(std::uint32_t Value, unsigned int Shift)
		{
			return (Value >> Shift) | (Value << (32 - Shift));
		}
		static FORCEINLINE std::uint64_t ROL64function(std::uint64_t Value, unsigned int Shift)
		{
			return (Value << Shift) | (Value >> (64 - Shift));
		}
		static FORCEINLINE std::uint64_t ROR64function(std::uint64_t Value, unsigned int Shift)
		{
			return (Value >> Shift) | (Value << (64 - Shift));
		}
	}

#if defined(_MSC_VER)
#define ROL8(VALUE,SHIFT) (_rotl8((VALUE), static_cast<unsigned char>(SHIFT)))
#define ROR8(VALUE,SHIFT) (_rotr8((VALUE), static_cast<unsigned char>(SHIFT)))
#define ROL16(VALUE,SHIFT) (_rotl16((VALUE), static_cast<unsigned char>(SHIFT)))
#define ROR16(VALUE,SHIFT) (_rotr16((VALUE), static_cast<unsigned char>(SHIFT)))
#define ROL32(VALUE,SHIFT) (_rotl((VALUE), static_cast<unsigned int>(SHIFT)))
#define ROR32(VALUE,SHIFT) (_rotr((VALUE), static_cast<unsigned int>(SHIFT)))
#if PROCESSOR_X64
#define ROL64(VALUE,SHIFT) (_rotl64((VALUE), (SHIFT)))
#define ROR64(VALUE,SHIFT) (_rotl64((VALUE), (SHIFT)))
#else
#define ROL64(VALUE,SHIFT) (Private::ROL64function((VALUE), (SHIFT)))
#define ROR64(VALUE,SHIFT) (Private::ROR64function((VALUE), (SHIFT)))
#endif
#else
#define ROL8(VALUE,SHIFT) (Private::ROL8function((VALUE), (SHIFT)))
#define ROR8(VALUE,SHIFT) (Private::ROR32function((VALUE), (SHIFT)))
#define ROL16(VALUE,SHIFT) (Private::ROL16function((VALUE), (SHIFT)))
#define ROR16(VALUE,SHIFT) (Private::ROR16function((VALUE), (SHIFT)))
#define ROL32(VALUE,SHIFT) (Private::ROL32function((VALUE), (SHIFT)))
#define ROR32(VALUE,SHIFT) (Private::ROR32function((VALUE), (SHIFT)))
#define ROL64(VALUE,SHIFT) (Private::ROL64function((VALUE), (SHIFT)))
#define ROR64(VALUE,SHIFT) (Private::ROR64function((VALUE), (SHIFT)))
#endif

	template<typename T>
	FORCEINLINE T Ror(T Value, unsigned int Shift)
	{
		return (T >> Shift) | (T << ((sizeof(T)* CHAR_BIT) - Shift))
	}
	template<typename T>
	FORCEINLINE T Rol(T Value, unsigned int Shift)
	{
		return (T << Shift) | (T >> ((sizeof(T)* CHAR_BIT) - Shift))
	}

	template<>
	FORCEINLINE std::uint8_t Ror<std::uint8_t>(std::uint8_t Value, unsigned int Shift)
	{
		return ROR8(Value, Shift);
	}
	template<>
	FORCEINLINE std::uint8_t Rol<std::uint8_t>(std::uint8_t Value, unsigned int Shift)
	{
		return ROL8(Value, Shift);
	}
	template<>
	FORCEINLINE std::int8_t Ror<std::int8_t>(std::int8_t Value, unsigned int Shift)
	{
		return static_cast<std::int8_t>(ROR8(Value, Shift));
	}
	template<>
	FORCEINLINE std::int8_t Rol<std::int8_t>(std::int8_t Value, unsigned int Shift)
	{
		return static_cast<std::int8_t>(ROL8(Value, Shift));
	}

	template<>
	FORCEINLINE std::uint16_t Ror<std::uint16_t>(std::uint16_t Value, unsigned int Shift)
	{
		return ROR16(Value, Shift);
	}
	template<>
	FORCEINLINE std::uint16_t Rol<std::uint16_t>(std::uint16_t Value, unsigned int Shift)
	{
		return ROL16(Value, Shift);
	}
	template<>
	FORCEINLINE std::int16_t Ror<std::int16_t>(std::int16_t Value, unsigned int Shift)
	{
		return static_cast<std::int16_t>(ROR16(Value, Shift));
	}
	template<>
	FORCEINLINE std::int16_t Rol<std::int16_t>(std::int16_t Value, unsigned int Shift)
	{
		return static_cast<std::int16_t>(ROL16(Value, Shift));
	}

	template<>
	FORCEINLINE std::uint32_t Ror<std::uint32_t>(std::uint32_t Value, unsigned int Shift)
	{
		return ROR32(Value, Shift);
	}
	template<>
	FORCEINLINE std::uint32_t Rol<std::uint32_t>(std::uint32_t Value, unsigned int Shift)
	{
		return ROL32(Value, Shift);
	}
	template<>
	FORCEINLINE std::int32_t Ror<std::int32_t>(std::int32_t Value, unsigned int Shift)
	{
		return static_cast<std::int32_t>(ROR32(Value, Shift));
	}
	template<>
	FORCEINLINE std::int32_t Rol<std::int32_t>(std::int32_t Value, unsigned int Shift)
	{
		return static_cast<std::int32_t>(ROL32(Value, Shift));
	}

	template<>
	FORCEINLINE std::uint64_t Ror<std::uint64_t>(std::uint64_t Value, unsigned int Shift)
	{
		return ROR64(Value, Shift);
	}
	template<>
	FORCEINLINE std::uint64_t Rol<std::uint64_t>(std::uint64_t Value, unsigned int Shift)
	{
		return ROL64(Value, Shift);
	}
	template<>
	FORCEINLINE std::int64_t Ror<std::int64_t>(std::int64_t Value, unsigned int Shift)
	{
		return static_cast<std::int64_t>(ROR64(Value, Shift));
	}
	template<>
	FORCEINLINE std::int64_t Rol<std::int64_t>(std::int64_t Value, unsigned int Shift)
	{
		return static_cast<std::int64_t>(ROL64(Value, Shift));
	}




	//Bitscan
	namespace Private
	{
		FORCEINLINE unsigned int LowLevelBitScanForward32(std::uint32_t Value)
		{
			//http://stackoverflow.com/questions/3465098/bit-twiddling-which-bit-is-set
			//http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
			static const unsigned int MultiplyDeBruijnBitPosition2[32] = { 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 };
			Value |= Value >> 1;
			Value |= Value >> 2;
			Value |= Value >> 4;
			Value |= Value >> 8;
			Value |= Value >> 16;
			return MultiplyDeBruijnBitPosition2[(std::uint32_t)(Value * 0x077CB531U) >> 27];
		}
		FORCEINLINE unsigned int LowLevelBitScanForward32(std::int32_t Value)
		{
			return LowLevelBitScanForward32(static_cast<std::uint32_t>(Value));
		}
		FORCEINLINE unsigned int LowLevelBitScanForward64(std::uint64_t Value)
		{
			//http://stackoverflow.com/questions/3465098/bit-twiddling-which-bit-is-set
			//http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
			//http://chessprogramming.wikispaces.com/De+Bruijn+sequence
			static const unsigned int MultiplyDeBruijnBitPosition2[64] = { 1, 2, 4, 8, 17, 34, 5, 11, 23, 47, 31, 63, 62, 61, 59, 55, 46, 29, 58, 53, 43, 22, 44, 24, 49, 35, 7, 15, 30, 60, 57, 51, 38, 12, 25, 50, 36, 9, 18, 37, 10, 21, 42, 20, 41, 19, 39, 14, 28, 56, 48, 33, 3, 6, 13, 27, 54, 45, 26, 52, 40, 16, 32 };
			Value |= Value >> 1;
			Value |= Value >> 2;
			Value |= Value >> 4;
			Value |= Value >> 8;
			Value |= Value >> 16;
			Value |= Value >> 32;
			return MultiplyDeBruijnBitPosition2[(std::uint32_t)(Value * 0x077CB531U) >> 27];
		}
		FORCEINLINE unsigned int LowLevelBitScanForward64(std::int64_t Value)
		{
			return LowLevelBitScanForward64(static_cast<std::uint64_t>(Value));
		}
	}

#ifdef _MSC_VER
	namespace Private
	{
		FORCEINLINE unsigned long LowLevelMsvcBitScanForward32Function(unsigned long Value)
		{
			unsigned long Result;
			_BitScanForward(&Result, Value);
			return Result;
		}
		FORCEINLINE unsigned long LowLevelMsvcBitScanReverse32Function(unsigned long Value)
		{
			unsigned long Result;
			_BitScanReverse(&Result, Value);
			return Result;
		}
#if PROCESSOR_X64
		FORCEINLINE unsigned long LowLevelMsvcBitScanForward64Function(unsigned long long Value)
		{
			unsigned long Result;
			_BitScanForward64(&Result, Value);
			return Result;
		}
		FORCEINLINE unsigned long LowLevelMsvcBitScanReverse64Function(unsigned long long Value)
		{
			unsigned long Result;
			_BitScanReverse64(&Result, Value);
			return Result;
		}
#else
		FORCEINLINE unsigned long LowLevelMsvcBitScanForward64Function(unsigned long long Value)
		{
			unsigned long Result;
			if (_BitScanForward(&Result, static_cast<unsigned long>(Value)))
				return Result;
			_BitScanForward(&Result, static_cast<unsigned long>(Value >> 32));
			return Result + 32;
		}
		FORCEINLINE unsigned long LowLevelMsvcBitScanReverse64Function(unsigned long long Value)
		{
			unsigned long Result;
			if (_BitScanReverse(&Result, static_cast<unsigned long>(Value >> 32)))
				return Result + 32;
			_BitScanReverse(&Result, static_cast<unsigned long>(Value));
			return Result;
		}
#endif
	}
#define BITSCANFORWARD8(VALUE) (Private::LowLevelMsvcBitScanForward32Function(static_cast<unsigned char>( VALUE )))
#define BITSCANREVERSE8(VALUE) (Private::LowLevelMsvcBitScanReverse32Function(static_cast<unsigned char>( VALUE )))
#define BITSCANFORWARD16(VALUE) (Private::LowLevelMsvcBitScanForward32Function(static_cast<unsigned short>( VALUE )))
#define BITSCANREVERSE16(VALUE) (Private::LowLevelMsvcBitScanReverse32Function(static_cast<unsigned short>( VALUE )))
#define BITSCANFORWARD32(VALUE) (Private::LowLevelMsvcBitScanForward32Function(static_cast<unsigned long>( VALUE )))
#define BITSCANREVERSE32(VALUE) (Private::LowLevelMsvcBitScanReverse32Function(static_cast<unsigned long>( VALUE )))
#define BITSCANFORWARD64(VALUE) (Private::LowLevelMsvcBitScanForward64Function(static_cast<unsigned long long>( VALUE )))
#define BITSCANREVERSE64(VALUE) (Private::LowLevelMsvcBitScanReverse64Function(static_cast<unsigned long long>( VALUE )))
#elif defined(__GNUC__) || defined(__clang__) || defined(__llvm__)
#define BITSCANFORWARD8(VALUE) (__builtin_ctz(static_cast<unsigned char>( VALUE )))
#define BITSCANREVERSE8(VALUE) (__builtin_clz(static_cast<unsigned char>( VALUE )))
#define BITSCANFORWARD16(VALUE) (__builtin_ctz(static_cast<unsigned short>( VALUE )))
#define BITSCANREVERSE16(VALUE) (__builtin_clz(static_cast<unsigned short>( VALUE )))
#define BITSCANFORWARD32(VALUE) (__builtin_ctz(static_cast<unsigned int>( VALUE )))
#define BITSCANREVERSE32(VALUE) (__builtin_clz(static_cast<unsigned int>( VALUE )))
#define BITSCANFORWARD64(VALUE) (__builtin_ctzll(static_cast<unsigned long long>( VALUE )))
#define BITSCANREVERSE64(VALUE) (__builtin_clzll(static_cast<unsigned long long>( VALUE )))
#else
#define BITSCANFORWARD8(VALUE) (Private::LowLevelBitScanForward32(static_cast<unsigned char>( VALUE )))
#define BITSCANREVERSE8(VALUE) (Private::LowLevelBitScanReserve32(static_cast<unsigned char>( VALUE )))
#define BITSCANFORWARD16(VALUE) (Private::LowLevelBitScanForward32(static_cast<unsigned short>( VALUE )))
#define BITSCANREVERSE16(VALUE) (Private::LowLevelBitScanReserve32(static_cast<unsigned short>( VALUE )))
#define BITSCANFORWARD32(VALUE) (Private::LowLevelBitScanForward32(static_cast<unsigned int>( VALUE )))
#define BITSCANREVERSE32(VALUE) (Private::LowLevelBitScanReserve32(static_cast<unsigned int>( VALUE )))
#define BITSCANFORWARD64(VALUE) (Private::LowLevelBitScanForward64(static_cast<unsigned long long>( VALUE )))
#define BITSCANREVERSE64(VALUE) (Private::LowLevelBitScanReserve64(static_cast<unsigned long long>( VALUE )))
#endif

	template<typename T>
	FORCEINLINE unsigned int BitScanForward(T Value)
	{
		unsigned int Result = 0;
		while (!(Value & (1 << Result)))
		if ((++Result) == (sizeof(T)* CHAR_BIT - 1))
			return sizeof(T)* CHAR_BIT - 1;
		return Result;
	}
	template<typename T>
	FORCEINLINE unsigned int BitScanReverse(T Value)
	{
		unsigned int Result = sizeof(T)* CHAR_BIT - 1;
		while (!(Value & (1 << Result)))
		if (!(--Result))
			return sizeof(T)* CHAR_BIT - 1;
		return (sizeof(T)* CHAR_BIT) - Result;
	}

	template<>
	FORCEINLINE unsigned int BitScanForward(std::uint8_t Value)
	{
		return BITSCANFORWARD8(Value);
	}
	template<>
	FORCEINLINE unsigned int BitScanReverse(std::uint8_t Value)
	{
		return BITSCANREVERSE8(Value);
	}
	template<>
	FORCEINLINE unsigned int BitScanForward(std::int8_t Value)
	{
		return BITSCANFORWARD8(static_cast<std::uint8_t>(Value));
	}
	template<>
	FORCEINLINE unsigned int BitScanReverse(std::int8_t Value)
	{
		return BITSCANREVERSE8(static_cast<std::uint8_t>(Value));
	}

	template<>
	FORCEINLINE unsigned int BitScanForward(std::uint16_t Value)
	{
		return BITSCANFORWARD16(Value);
	}
	template<>
	FORCEINLINE unsigned int BitScanReverse(std::uint16_t Value)
	{
		return BITSCANREVERSE16(Value);
	}
	template<>
	FORCEINLINE unsigned int BitScanForward(std::int16_t Value)
	{
		return BITSCANFORWARD16(static_cast<std::uint16_t>(Value));
	}
	template<>
	FORCEINLINE unsigned int BitScanReverse(std::int16_t Value)
	{
		return BITSCANREVERSE16(static_cast<std::uint16_t>(Value));
	}

	template<>
	FORCEINLINE unsigned int BitScanForward(std::uint32_t Value)
	{
		return BITSCANFORWARD32(Value);
	}
	template<>
	FORCEINLINE unsigned int BitScanReverse(std::uint32_t Value)
	{
		return BITSCANREVERSE32(Value);
	}
	template<>
	FORCEINLINE unsigned int BitScanForward(std::int32_t Value)
	{
		return BITSCANFORWARD32(static_cast<std::uint32_t>(Value));
	}
	template<>
	FORCEINLINE unsigned int BitScanReverse(std::int32_t Value)
	{
		return BITSCANREVERSE32(static_cast<std::uint32_t>(Value));
	}

	template<>
	FORCEINLINE unsigned int BitScanForward(std::uint64_t Value)
	{
		return BITSCANFORWARD64(Value);
	}
	template<>
	FORCEINLINE unsigned int BitScanReverse(std::uint64_t Value)
	{
		return BITSCANREVERSE64(Value);
	}
	template<>
	FORCEINLINE unsigned int BitScanForward(std::int64_t Value)
	{
		return BITSCANFORWARD64(static_cast<std::uint64_t>(Value));
	}
	template<>
	FORCEINLINE unsigned int BitScanReverse(std::int64_t Value)
	{
		return BITSCANREVERSE64(static_cast<std::uint64_t>(Value));
	}





	//NumberOfSetBits
	template<typename T>
	FORCEINLINE unsigned int NumberOfSetBits(T Value)
	{
		if (sizeof(T) == 1)
			return NumberOfSetBits<std::uint8_t>(*(reinterpret_cast<std::uint8_t*>(&Value)));
		else if (sizeof(T) == 2)
			return NumberOfSetBits<std::uint16_t>(*(reinterpret_cast<std::uint16_t*>(&Value)));
		else if (sizeof(T) == 3)
			return NumberOfSetBits<std::uint8_t>(*(reinterpret_cast<std::uint8_t*>(&Value) + 2)) + NumberOfSetBits<std::uint16_t>(*(reinterpret_cast<std::uint16_t*>(&Value)));
		else if (sizeof(T) == 4)
			return NumberOfSetBits<std::uint32_t>(*(reinterpret_cast<std::uint32_t*>(&Value)));
		else
		{
			unsigned int Result = 0;
			std::size_t i = 0;
			for (; i < (sizeof(T) >> 2); i++)
				Result += NumberOfSetBits<std::uint32_t>(*(reinterpret_cast<std::uint32_t*>(&Value) + i));
			if ((sizeof(T)& 3) == 1)
				Result += NumberOfSetBits<std::uint8_t>(*(reinterpret_cast<std::uint8_t*>(reinterpret_cast<std::uint32_t*>(&Value) + i)));
			else if ((sizeof(T)& 3) == 2)
				Result += NumberOfSetBits<std::uint16_t>(*(reinterpret_cast<std::uint16_t*>(reinterpret_cast<std::uint32_t*>(&Value) + i)));
			else if ((sizeof(T)& 3) == 3)
				Result += NumberOfSetBits<std::uint8_t>(*(reinterpret_cast<std::uint8_t*>(reinterpret_cast<std::uint32_t*>(&Value) + i) + 2)) + NumberOfSetBits<std::uint16_t>(*(reinterpret_cast<std::uint16_t*>(reinterpret_cast<std::uint32_t*>(&Value) + i)));
			return Result;
		}
	}
	template<>
	FORCEINLINE unsigned int NumberOfSetBits(std::uint32_t Value)
	{
		Value -= ((Value >> 1) & 0x55555555);
		Value = (Value & 0x33333333) + ((Value >> 2) & 0x33333333);
		return static_cast<unsigned int>((((Value + (Value >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24);
	}
	template<>
	FORCEINLINE unsigned int NumberOfSetBits(std::int32_t Value)
	{
		return NumberOfSetBits<std::uint32_t>(static_cast<std::uint32_t>(Value));
	}
	template<>
	FORCEINLINE unsigned int NumberOfSetBits(std::uint8_t Value)
	{
		return NumberOfSetBits<std::uint32_t>(static_cast<std::uint32_t>(Value));
	}
	template<>
	FORCEINLINE unsigned int NumberOfSetBits(std::int8_t Value)
	{
		return NumberOfSetBits<std::uint32_t>(static_cast<std::uint32_t>(Value));
	}
	template<>
	FORCEINLINE unsigned int NumberOfSetBits(std::uint16_t Value)
	{
		return NumberOfSetBits<std::uint32_t>(static_cast<std::uint32_t>(Value));
	}
	template<>
	FORCEINLINE unsigned int NumberOfSetBits(std::int16_t Value)
	{
		return NumberOfSetBits<std::uint32_t>(static_cast<std::uint32_t>(Value));
	}
	template<>
	FORCEINLINE unsigned int NumberOfSetBits(std::uint64_t Value)
	{
		Value -= ((Value >> 1) & 0x5555555555555555);
		Value = (Value & 0x3333333333333333) + ((Value >> 2) & 0x3333333333333333);
		return static_cast<unsigned int>((((Value + (Value >> 4)) & 0xF0F0F0F0F0F0F0F) * 0x101010101010101) >> 56);
	}
	template<>
	FORCEINLINE unsigned int NumberOfSetBits(std::int64_t Value)
	{
		return NumberOfSetBits<std::uint64_t>(static_cast<std::uint64_t>(Value));
	}

	template<typename T>
	FORCEINLINE unsigned int NumberOfClearBits(T Value)
	{
		return (sizeof(T)* CHAR_BIT) - NumberOfSetBits<T>(Value);
	}



	namespace Private
	{
		FORCEINLINE std::uint32_t LowLevelByteSwap32(std::uint32_t Value)
		{
			return (Value >> 24) | ((Value >> 8) & 0x0000FF00) | ((Value << 8) & 0x00FF0000) | (Value << 24);
		}
		FORCEINLINE std::uint64_t LowLevelByteSwap64(std::uint64_t Value)
		{
			return
				(Value >> 56) |
				((Value >> 40) & 0x000000000000FF00) |
				((Value >> 24) & 0x0000000000FF0000) |
				((Value >> 8) & 0x00000000FF000000) |
				((Value << 8) & 0x000000FF00000000) |
				((Value << 24) & 0x0000FF0000000000) |
				((Value << 40) & 0x00FF000000000000) |
				(Value << 56);
		}
	}
#define BYTESWAP8(VALUE) (VALUE)
#define BYTESWAP06(VALUE) (ROR16((VALUE), 8))
#if defined(_MSC_VER)
#define BYTESWAP32(VALUE) (_byteswap_ulong(VALUE))
#define BYTESWAP64(VALUE) (_byteswap_uint64(VALUE))
#elif defined(__GNUC__) || defined(__clang__) || defined(__llvm__)
#define BYTESWAP32(VALUE) (__builtin_bswap32(VALUE))
#define BYTESWAP64(VALUE) (__builtin_bswap64(VALUE))
#else
#define BYTESWAP32(VALUE) (Private::LowLevelByteSwap32(VALUE))
#define BYTESWAP64(VALUE) (Private::LowLevelByteSwap64(VALUE))
#endif

	template<typename T>
	FORCEINLINE T ByteSwap(T Value)
	{
		uint8_t* const ValuePtr = reinterpret_cast<uint8_t*>(&Value);
		for (std::size_t i = 0; i < (sizeof(Value) >> 1); i++)
			std::swap(ValuePtr[i], ValuePtr[(sizeof(Value)-1) - i]);
		return Value;
	}
	template<>
	FORCEINLINE std::uint8_t ByteSwap(const std::uint8_t Value)
	{
		return Value;
	}
	template<>
	FORCEINLINE std::int8_t ByteSwap(const std::int8_t Value)
	{
		return Value;
	}
	template<>
	FORCEINLINE std::uint16_t ByteSwap(const std::uint16_t Value)
	{
		return BYTESWAP06(Value);
	}
	template<>
	FORCEINLINE std::int16_t ByteSwap(const std::int16_t Value)
	{
		return static_cast<std::int16_t>(BYTESWAP06(static_cast<std::uint16_t>(Value)));
	}
	template<>
	FORCEINLINE std::uint32_t ByteSwap(const std::uint32_t Value)
	{
		return BYTESWAP32(Value);
	}
	template<>
	FORCEINLINE std::int32_t ByteSwap(const std::int32_t Value)
	{
		return static_cast<std::int32_t>(BYTESWAP32(static_cast<std::uint32_t>(Value)));
	}
	template<>
	FORCEINLINE std::uint64_t ByteSwap(const std::uint64_t Value)
	{
		return BYTESWAP64(Value);
	}
	template<>
	FORCEINLINE std::int64_t ByteSwap(const std::int64_t Value)
	{
		return static_cast<std::int64_t>(BYTESWAP64(static_cast<std::uint64_t>(Value)));
	}

	//std::size_t Support

#if SIZE_MAX == UINT8_MAX
#define ROLSIZET(VALUE,SHIFT) ROL8(VALUE,SHIFT)
#define RORSIZET(VALUE,SHIFT) ROR8(VALUE,SHIFT)
#define BITSCANFORWARDSIZE(VALUE) BITSCANFORWARD8(VALUE,SHIFT)
#define BITSCANREVERSESIZE(VALUE) BITSCANREVERSE8(VALUE,SHIFT)
#define BYTESWAPSIZE(VALUE) BYTESWAP8(VALUE)
#define SIZE_BITS 8
#elif SIZE_MAX == UINT16_MAX
#define ROLSIZET(VALUE,SHIFT) ROL16(VALUE,SHIFT)
#define RORSIZET(VALUE,SHIFT) ROR16(VALUE,SHIFT)
#define BITSCANFORWARDSIZE(VALUE) BITSCANFORWARD16(VALUE,SHIFT)
#define BITSCANREVERSESIZE(VALUE) BITSCANREVERSE16(VALUE,SHIFT)
#define BYTESWAPSIZE(VALUE) BYTESWAP06(VALUE)
#define SIZE_BITS 16
#elif SIZE_MAX == UINT32_MAX
#define ROLSIZET(VALUE,SHIFT) ROL32(VALUE,SHIFT)
#define RORSIZET(VALUE,SHIFT) ROR32(VALUE,SHIFT)
#define BITSCANFORWARDSIZE(VALUE) BITSCANFORWARD32(VALUE,SHIFT)
#define BITSCANREVERSESIZE(VALUE) BITSCANREVERSE32(VALUE,SHIFT)
#define BYTESWAPSIZE(VALUE) BYTESWAP32(VALUE)
#define SIZE_BITS 32
#elif SIZE_MAX == UINT64_MAX
#define ROLSIZET(VALUE,SHIFT) ROL64(VALUE,SHIFT)
#define RORSIZET(VALUE,SHIFT) ROR64(VALUE,SHIFT)
#define BITSCANFORWARDSIZE(VALUE) BITSCANFORWARD64(VALUE,SHIFT)
#define BITSCANREVERSESIZE(VALUE) BITSCANREVERSE64(VALUE,SHIFT)
#define BYTESWAPSIZE(VALUE) BYTESWAP64(VALUE)
#define SIZE_BITS 64
#else
#define ROLSIZE(VALUE,SHIFT) (Ror<std::size_t>((VALUE),(SHIFT)))
#define RORSIZE(VALUE,SHIFT) (Rol<std::size_t>((VALUE),(SHIFT)))
#define BITSCANFORWARDSIZE(VALUE) (BitScanForward<std::size_t>((VALUE),(SHIFT)))
#define BITSCANREVERSESIZE(VALUE) (BitScanReverse<std::size_t>((VALUE),(SHIFT)))
#define BYTESWAPSIZE(VALUE) (ByteSwap<std::size_t>(VALUE))
#define SIZE_BITS (sizeof(std::size_t) * CHAR_BIT)
	//#error std::size_t dont have 8,16,32 or 64 bits
#endif



#ifndef DOXYGEN_SHOULD_SKIP_THIS
#if defined(PROCESSOR_X86) || defined(PROCESSOR_X64)
	struct CpuidData
	{
		union
		{
			struct
			{
				std::uint32_t Eax;
				std::uint32_t Ebx;
				std::uint32_t Edx;
				std::uint32_t Ecx;
			};
			std::uint32_t RawData[4];
		};
		FORCEINLINE CpuidData()
		{
			this->Eax = 0;
			this->Ebx = 0;
			this->Edx = 0;
			this->Ecx = 0;
		}
	};
#if defined(_MSC_VER)
	FORCEINLINE CpuidData CpuidGet(std::uint32_t Eax)
	{
		CpuidData Result;
		__cpuid(reinterpret_cast<int*>(&(Result.RawData)), Eax);
		std::swap(Result.Edx, Result.Ecx);
		return Result;
	}
	//FORCEINLINE CpuidData CpuidGet(std::uint32_t Eax, std::uint32_t Ecx)
	//{
	//	CpuidData Result;
	//	__cpuidex(reinterpret_cast<int*>(&(Result.RawData)), Eax, Ecx);
	//  std::swap(Result.Edx, Result.Ecx);
	//	return Result;
	//}
#elif defined(__GNUC__) 
#if defined(__i386__) || defined(__i386) || defined(i386)
	FORCEINLINE CpuidData CpuidGet(std::uint32_t Eax)
	{
		CpuidData Result;
		asm volatile("pushl %%ebx;"
			"cpuid;"
			"mov %%ebx, %0"
			"popl %%ebx;"
			: "=m"(&(Result.Ebx)), "=a"(Result.Eax), "=c"(Result.Ecx), "=d"(Result.Edx)
			: "a"(Eax));
		return Result;
	}
#else
	FORCEINLINE CpuidData CpuidGet(std::uint32_t Eax)
	{
		CpuidData Result;
		asm volatile("cpuid"
			: "=a"(Result.Eax), "=b"(Result.Ebx), "=c"(Result.Ecx), "=d"(Result.Edx)
			: "a"(Eax));
		return Result;
	}
#endif
#elif defined(__clang__) || defined(__llvm__)
	FORCEINLINE CpuidData CpuidGet(std::uint32_t Eax)
	{
		CpuidData Result;
		__get_cpuid(Eax, &(Result.Eax), &(Result.Ebx), &(Result.Ecx), &(Result.Edx));
		return Result;
	}
#else
	FORCEINLINE CpuidData GetCpuid(std::uint32_t Eax)
	{
		return CpuidData();
	}
#error CPUID NOT SUPPORTED
#endif
#endif
#else
	FORCEINLINE CpuidData GetCpuid(std::uint32_t Eax);
#endif
	extern const CpuidData Cpuid0x0;
	extern const CpuidData Cpuid0x1;
	extern const CpuidData Cpuid0x2;
	extern const CpuidData Cpuid0x7;
	extern const CpuidData Cpuid0x80000001;

#if WINDOWS || LINUX
#include <malloc.h>
#elif defined (BSD)
#include <malloc/malloc.h>
#endif

	FORCEINLINE std::size_t MallocGetAllocSize(const void* Ptr)
	{
#if WINDOWS
		return _msize(const_cast<void*>(Ptr));
#elif LINUX
		return malloc_usable_size(const_cast<void*>(Ptr));
#elif BSD
		return malloc_good_size(malloc_size(Ptr));
#else
#error Unknown OS
#endif
	}

	template<typename T>
	inline void FastMoveN(T* const PtrDestionation, T* const PtrSource, const std::size_t Size)
	{
#if defined(_MSC_VER) && (_MSC_VER > 1600)
		if (std::is_trivially_move_constructible<T>::value || std::is_pod<T>::value)
#else
		if (std::is_pod<T>::value)
#endif
			std::memcpy(PtrDestionation, PtrSource, Size * sizeof(T));
		else
		for (std::size_t i = 0; i < Size; i++)
			new (PtrDestionation + i) T(std::move(PtrSource[i]));
	}
	template<typename T>
	inline void FastCopyN(T* const PtrDestionation, const T* PtrSource, const std::size_t Size)
	{
#if defined(_MSC_VER) && (_MSC_VER > 1600)
		if (std::is_trivially_copy_constructible<T>::value || std::is_pod<T>::value)
#else
		if (std::is_pod<T>::value)
#endif
			std::memcpy(PtrDestionation, PtrSource, Size * sizeof(T));
		else
		for (std::size_t i = 0; i < Size; i++)
			new (PtrDestionation + i) T(PtrSource[i]);
	}
	template<typename T>
	inline void FastDestructN(T* const Data, const std::size_t Size)
	{
#if defined(_MSC_VER) && (_MSC_VER > 1600)
		if (!(std::is_trivially_destructible<T>::value || std::is_pod<T>::value))
#else
		if (!std::is_pod<T>::value)
#endif
		for (std::size_t i = 0; i < Size; i++)
			Data[i].~T();
	}
	template<typename T>
	inline void FastDestruct(T& Data)
	{
#if defined(_MSC_VER) && (_MSC_VER > 1600)
		if (!(std::is_trivially_destructible<T>::value || std::is_pod<T>::value))
#else
		if (!std::is_pod<T>::value)
#endif
			Data.~T();
	}
	template<typename T>
	T* SafeRealloc(T* const Data, const std::size_t NewSize)
	{
#if defined(_MSC_VER) && (_MSC_VER > 1600)
		if (std::is_trivially_move_constructible<T>::value || std::is_pod<T>::value)
#else
		if (std::is_pod<T>::value)
#endif
		{
			T* const Result = reinterpret_cast<T*>(std::realloc(Data, NewSize * sizeof(T)));
			if (Result)
				return Result;
			else
			{
				std::free(Data);
				throw std::bad_alloc();
			}
		}
		else
		{
			T* NewBuffer;
			EXCTRY
			{
				NewBuffer = reinterpret_cast<T*>(std::malloc(NewSize * sizeof(T)));
				for (std::size_t i = 0; i < NewSize; i++)
					new (NewBuffer + i) T(std::move(Data[i]));
			}
			EXCFINALLY
				(
				std::free(Data);
			)
				return NewBuffer;
		}
	}
	template<typename T>
	char* SafeRealloc(char* const Data, const std::size_t NewSize, const size_t PrependSize, const size_t AppendSize)
	{
#if defined(_MSC_VER) && (_MSC_VER > 1600)
		if (std::is_trivially_move_constructible<T>::value || std::is_pod<T>::value)
#else
		if (std::is_pod<T>::value)
#endif
		{
			char* const Result = reinterpret_cast<char*>(std::realloc(Data, NewSize * sizeof(T)+PrependSize + AppendSize));
			if (Result)
				return Result;
			else
			{
				std::free(Data);
				throw std::bad_alloc();
			}
		}
		else
		{
			char* NewBuffer;
			EXCTRY
			{
				NewBuffer = reinterpret_cast<char*>(std::malloc(NewSize * sizeof(T)+PrependSize + AppendSize));
				T* const NewBufferData = reinterpret_cast<T*>(NewBuffer + PrependSize);
				T* const OldData = reinterpret_cast<T*>(Data + PrependSize);
				for (std::size_t i = 0; i < NewSize; i++)
					new (NewBufferData + i) T(std::move(OldData[i]));
				std::memcpy(NewBuffer, Data, PrependSize);
				std::memcpy(NewBuffer + (NewSize * sizeof(T)+PrependSize), Data + (NewSize * sizeof(T)+PrependSize), AppendSize);
			}
			EXCFINALLY
				(
				std::free(Data);
			)
				return NewBuffer;
		}
	}

	//http://stackoverflow.com/questions/9291336/decltype-and-the-scope-operator-in-c
#define DECLTYPE(VAR) std::identity<decltype(VAR)>::type




#if defined(__llvm__) || defined(__clang__) || defined(__GNUC__)
#define CONSTRUCTHANDLER(NAME) \
	__attribute__((constructor)) void ConstructHandler_InternalConstruct ## NAME()
#define CONSTRUCTHANDLER_END

#define DESTRUCTHANDLER(NAME) \
	__attribute__((destructor)) void DestructHandler_InternalDestruct ## NAME()
#define DESTRUCTHANDLER_END

#else
#define CONSTRUCTHANDLER(NAME) \
	struct ConstructHandler_InternalConstruct ## NAME ## Type \
	{ \
	public: \
	ConstructHandler_InternalConstruct ## NAME ## Type();  \
	} ConstructHandler_InternalConstruct ## NAME; \
	ConstructHandler_InternalConstruct ## NAME ## Type::ConstructHandler_InternalConstruct ## NAME ## Type()

#define DESTRUCTHANDLER(NAME) \
	struct DestructHandler_InternalDestruct ## NAME ## Type \
	{ \
	public: \
	~DestructHandler_InternalDestruct ## NAME ## Type(); \
	} DestructHandler_InternalDestruct ## NAME; \
	DestructHandler_InternalDestruct ## NAME ## Type::DestructHandler_InternalDestruct ## NAME ## Type()
#endif

#if LONG_MAX < INT64_MAX
#define FSEEK_INT64_FUNC _fseeki64
#define FTELL_INT64_FUNC _ftelli64
#else
#define FSEEK_INT64_FUNC fseek
#define FTELL_INT64_FUNC ftell
#endif
	std::uint64_t fgetsize(std::FILE* const File);
	std::FILE* fopenw(const wchar_t* Name, const char* Mode);



#endif